package org.tulkas.base;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.tulkas.init.IAppPostInitializer;
import org.tulkas.util.FileUtil;

/**
 * @author <a href="mailto:tulkas.web@gmail.com">Tulkas</a>
 *
 */
public class TulkasApplicationContext extends XmlWebApplicationContext
		implements ITulkasApplicationContext {
	protected static final String CONFIG_PATH = "META-INF/applicationContext.xml";
	public static final String PARAM_NAME_DEBUG = "debug";

	private static Logger logger = LoggerFactory
			.getLogger(TulkasApplicationContext.class);

	private Exception initError = null;

	@Override
	public String[] getConfigLocations() {
		try {
			Enumeration<URL> em = this.getClassLoader().getResources(
					CONFIG_PATH);
			List<String> ret = new ArrayList<String>();
			while (em.hasMoreElements()) {
				ret.add(em.nextElement().toString());
			}
			return ret.toArray(new String[0]);
		} catch (IOException e) {
			logger.error("Error initialization application context", e);
			return new String[0];
		}
	}

	@Override
	public void refresh() {
		logger.info("Tulkas application context refresh begin.");
		initError = null;
		//		LogManager.getInstance().setSystemInitialized(false);
		try {
			super.refresh();
		} catch (Exception e) {
			logger.error("Initialization Error. []" + e.getMessage(), e);
			initError = e;
		}
		logger.info("Tulkas Robot initialization done.");
		//		LogManager.getInstance().setSystemInitialized(true);
	}

	@Override
	public boolean isDebug() {
		String isDebug = getServletContext().getInitParameter(PARAM_NAME_DEBUG);
		return "true".equalsIgnoreCase(isDebug);
	}

	@Override
	protected void finishBeanFactoryInitialization(
			ConfigurableListableBeanFactory beanFactory) {
		super.finishBeanFactoryInitialization(beanFactory);
		Map<String, IAppPostInitializer> map = getBeansOfType(IAppPostInitializer.class);
		List<IAppPostInitializer> pOrdered = new ArrayList<IAppPostInitializer>();
		List<IAppPostInitializer> ordered = new ArrayList<IAppPostInitializer>();
		List<IAppPostInitializer> noOrdered = new ArrayList<IAppPostInitializer>();
		for (IAppPostInitializer initializer : map.values()) {
			if (initializer instanceof PriorityOrdered) {
				pOrdered.add(initializer);
			} else if (initializer instanceof Ordered) {
				ordered.add(initializer);
			} else {
				noOrdered.add(initializer);
			}
		}

		OrderComparator.sort(pOrdered);
		for (IAppPostInitializer initializer : pOrdered) {
			initializer.contextInit(this);
		}
		OrderComparator.sort(ordered);
		for (IAppPostInitializer initializer : ordered) {
			initializer.contextInit(this);
		}
		OrderComparator.sort(noOrdered);
		for (IAppPostInitializer initializer : noOrdered) {
			initializer.contextInit(this);
		}
	}

	public Exception getInitError() {
		return initError;
	}

	public String getRootPath() {
		return FileUtil.trimFilePath(getServletContext().getRealPath("/"));
	}
}
